home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 1 / Meeting Pearls Vol 1 (1994).iso / installed_progs / util / pgp / pgpamiga / source / more.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-28  |  15.6 KB  |  494 lines

  1. /*      more.c  - Unix-style "more" paging output for PGP.
  2.         PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.
  3.  
  4.         (c) Copyright 1990-1992 by Philip Zimmermann.  All rights reserved.
  5.         The author assumes no liability for damages resulting from the use
  6.         of this software, even if the damage results from defects in this
  7.         software.  No warranty is expressed or implied.
  8.  
  9.         All the source code Philip Zimmermann wrote for PGP is available for
  10.         free under the "Copyleft" General Public License from the Free
  11.         Software Foundation.  A copy of that license agreement is included in
  12.         the source release package of PGP.  Code developed by others for PGP
  13.         is also freely available.  Other code that has been incorporated into
  14.         PGP from other sources was either originally published in the public
  15.         domain or was used with permission from the various authors.  See the
  16.         PGP User's Guide for more complete information about licensing,
  17.         patent restrictions on certain algorithms, trademarks, copyrights,
  18.         and export controls.
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #ifdef UNIX
  26. #include <sys/types.h>
  27. #include "system.h"
  28. #endif
  29. #ifdef AMIGA
  30. #include "system.h"
  31. #endif
  32. #ifdef sco
  33. #include <sys/stream.h>
  34. #include <sys/ptem.h>
  35. FILE *popen();
  36. #endif
  37. #include "mpilib.h"
  38. #include "language.h"
  39. #include "fileio.h"
  40. #include "pgp.h"
  41. #include "more.h"
  42. #include "charset.h"
  43.  
  44. #ifdef MSDOS
  45. #ifndef __GO32__
  46. #include <conio.h>
  47. #endif
  48. #define DEFAULT_LINES   25      /* MSDOS actually has a 25-line screen */
  49. #else
  50. #define DEFAULT_LINES   24
  51. #endif /* MSDOS */
  52. #define DEFAULT_COLUMNS 80
  53.  
  54. static int screen_lines = DEFAULT_LINES, screen_columns = DEFAULT_COLUMNS;
  55.  
  56. #define TAB             0x09            /* ASCII tab char */
  57. #define CR              '\r'            /* Carriage return char */
  58. #define LF              '\n'            /* Linefeed */
  59.  
  60. /* Get the screen size for 'more'.  The environment variables $LINES and
  61.    $COLUMNS will be used if they exist.  If not, then the TIOCGWINSZ call to
  62.    ioctl() is used (if it is defined).  If not, then the TIOCGSIZE call to
  63.    ioctl() is used (if it is defined).  If not, then the WIOCGETD call to
  64.    ioctl() is used (if it is defined).  If not, then get the info from
  65.    terminfo/termcap (if it is there).  Otherwise, assume we have a 24x80
  66.    model 33.
  67.  
  68.    That was for Unix.
  69.  
  70.    For DOS, just assume 24x80. */
  71.  
  72. #ifdef UNIX
  73. /* Try to access terminfo through the termcap-interface in the curses library
  74.    (which requires linking with -lcurses) or use termcap directly (which
  75.    requires linking with -ltermcap) */
  76.  
  77. #ifndef USE_TERMCAP
  78. #ifdef USE_TERMINFO
  79. #define USE_TERMCAP
  80. #endif
  81. #ifdef USE_CURSES
  82. #define USE_TERMCAP
  83. #endif
  84. #endif
  85.  
  86. #ifdef USE_TERMCAP
  87. #define TERMBUFSIZ    1024
  88. #define UNKNOWN_TERM  "unknown"
  89. #define DUMB_TERMBUF  "dumb:co#80:hc:"
  90.  
  91.   extern int  tgetent(), tgetnum();
  92. #endif
  93.  
  94. /* Try to get TIOCGWINSZ from termios.h, then from sys/ioctl.h */
  95. #ifndef NOTERMIO
  96. #ifdef SVR2
  97. #include <termio.h>
  98. #else
  99. #include <termios.h>
  100. #endif /* SVR2 */
  101. #endif
  102.  
  103. #ifndef SVR2
  104. #ifndef TIOCGWINSZ
  105. #ifndef TIOCGSIZE
  106. #ifndef WIOCGETD
  107. #include <sys/ioctl.h>
  108. #endif /* not WIOCGETD */
  109. #endif /* not TIOCGSIZE */
  110. #endif /* not TIOCGWINSZ */
  111.  
  112. /* If we still dont have TIOCGWINSZ (or TIOCGSIZE) try for WIOCGETD */
  113. #ifndef TIOCGWINSZ
  114. #ifndef TIOCGSIZE
  115. #ifndef WIOCGETD
  116. #include <sgtty.h>
  117. #endif /* not WIOCGETD */
  118. #endif /* not TIOCGSIZE */
  119. #endif /* not TIOCGWINSZ */
  120. #endif /* not SVR2 */
  121. #endif  /* UNIX */
  122.  
  123. static void getScreenSize(void) /* Rot bilong kargo */
  124. /* Return the screen size */
  125. {
  126.         char *envLines, *envColumns;
  127.         long rowTemp = 0, colTemp = 0;
  128. #ifdef UNIX
  129. #ifdef USE_TERMCAP
  130.         char termBuffer[TERMBUFSIZ], *termInfo;
  131. #endif
  132. #ifdef TIOCGWINSZ
  133.         struct winsize windowInfo;
  134. #else
  135. #ifdef TIOCGSIZE
  136.         struct ttysize windowInfo;
  137. #else
  138. #ifdef WIOCGETD
  139.           struct uwdata windowInfo;
  140. #endif /* WIOCGETD */
  141. #endif /* TIOCGSIZE */
  142. #endif /* TIOCGWINSZ */
  143.  
  144.         /* Make sure that we're outputting to a terminal */
  145.         if (!isatty(fileno(stderr)))
  146.         {
  147.                 screen_lines = DEFAULT_LINES;
  148.                 screen_columns = DEFAULT_COLUMNS;
  149.                 return;
  150.         }
  151.         screen_lines = screen_columns = 0;
  152. #endif  /* UNIX */
  153.  
  154.         /* LINES & COLUMNS environment variables override everything else */
  155.         envLines = my_getenv("LINES");
  156.         if (envLines != NULL && (rowTemp = atol(envLines)) > 0 )
  157.                 screen_lines = (int)rowTemp;
  158.  
  159.         envColumns = my_getenv("COLUMNS");
  160.         if (envColumns != NULL && (colTemp = atol(envColumns)) > 0 )
  161.                 screen_columns = (int)colTemp;
  162.  
  163. #ifdef UNIX
  164. #ifdef TIOCGWINSZ
  165.         /* See what ioctl() has to say (overrides terminfo & termcap) */
  166.         if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),TIOCGWINSZ,&windowInfo) != -1)
  167.         {       if (!screen_lines && windowInfo.ws_row > 0)
  168.                         screen_lines = (int)windowInfo.ws_row;
  169.  
  170.                 if (!screen_columns && windowInfo.ws_col > 0 )
  171.                         screen_columns = (int)windowInfo.ws_col;
  172.         }
  173. #else
  174. #ifdef TIOCGSIZE
  175.         /* See what ioctl() has to say (overrides terminfo & termcap) */
  176.         if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),TIOCGSIZE,&windowInfo) != -1)
  177.         {       if (!screen_lines && windowInfo.ts_lines > 0)
  178.                         screen_lines = (int)windowInfo.ts_lines;
  179.  
  180.                 if (!screen_columns && windowInfo.ts_cols > 0)
  181.                         screen_columns = (int)windowInfo.ts_cols;
  182.         }
  183. #else
  184. #ifdef WIOCGETD
  185.         /* See what ioctl() has to say (overrides terminfo & termcap) */
  186.         if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),WIOCGETD,&windowInfo) != -1)
  187.         {       if (!screen_lines && windowInfo.uw_height > 0)
  188.                         screen_lines = (int)(windowInfo.uw_height / windowInfo.uw_vs);
  189.  
  190.                 if (!screen_columns && windowInfo.uw_width > 0)
  191.                         screen_columns = (int)(windowInfo.uw_width / windowInfo.uw_hs);
  192.         }       /* You are in a twisty maze of standards, all different */
  193. #endif
  194. #endif
  195. #endif
  196.  
  197. #ifdef USE_TERMCAP
  198.         /* See what terminfo/termcap has to say */
  199.         if (!screen_lines || !screen_columns)
  200.         {       if ((termInfo = my_getenv("TERM")) == (char *)NULL)
  201.                         termInfo = UNKNOWN_TERM;
  202.  
  203.                 if ((tgetent(termBuffer, termInfo) <= 0))
  204.                         strcpy(termBuffer,DUMB_TERMBUF);
  205.  
  206.                 if (!screen_lines && (rowTemp = tgetnum("li")) > 0)
  207.                                 screen_lines = (int)rowTemp;
  208.  
  209.                 if (!screen_columns && (colTemp = tgetnum("co")) > 0)
  210.                                 screen_columns = (int)colTemp;
  211.         }
  212. #endif
  213.         if (screen_lines == 0)                  /* nothing worked, use defaults */
  214.                 screen_lines = DEFAULT_LINES;
  215.         if (screen_columns == 0)
  216.                 screen_columns = DEFAULT_COLUMNS;
  217. #endif  /* UNIX */
  218. }
  219.  
  220. /* Certain systems need to go into a "break" mode */
  221. #ifdef UNIX
  222. #define NEEDBREAK
  223. #endif
  224. #ifdef AMIGA
  225. #define NEEDBREAK
  226. #endif
  227. #ifdef ATARI
  228. #define reverse_attr()          printf("\033p")
  229. #define norm_attr()                     printf("\033q")
  230. #else
  231. #define reverse_attr()
  232. #define norm_attr()
  233. #endif
  234.  
  235.  
  236. #ifdef VMS
  237. char pager[80] = "Type/Page";   /* default pager for VMS */
  238. #else   /* not VMS */
  239. char pager[80] = "";
  240. #endif  /* not VMS */
  241.  
  242.  
  243. int more_file(char *fileName)
  244. /* Blort a file to the screen with page breaks, intelligent handling of line
  245.    terminators, truncation of overly long lines, and zapping of illegal
  246.    chars */
  247. {
  248.         FILE *inFile;
  249.         int lines = 0,ch,i,chars = 0, c;
  250.         long fileLen;
  251.         char cmd[MAX_PATH];
  252.         char buf[16];
  253.         int lineno;
  254.         char *p;
  255.  
  256.         if ((inFile = fopen(fileName,FOPRBIN)) == NULL)
  257.                 /* Can't see how this could fail since we just created the file */
  258.                 return(-1);
  259.  
  260.  /*
  261.   * I took this commandblock out, because the fread() is causing problems
  262.   * with the latest version of my C-Compiler and I didn't find this part
  263.   * really useful.
  264.   *                                                             -peter
  265.   *
  266.   *         fread(buf, 1, 16, inFile);
  267.   *         if (compressSignature( (byte *) buf) >= 0) {
  268.   *                 fprintf(pgpout, PSTR("\n\007File '%s' is not a text file; cannot display.\n"), fileName);
  269.   *                 return(-1);
  270.   *         }
  271.   */
  272.  
  273.         /* PAGER set in config.txt overrides environment variable,
  274.                 set PAGER in config.txt to 'pgp' to use builtin pager */
  275.         if (pager[0] == '\0')
  276.         {
  277.                 if ((p = my_getenv("PAGER")) != NULL)
  278.                         strncpy(pager, p, sizeof(pager) - 1);
  279.         }
  280.         if (strcmp(pager, "cat") == 0)
  281.         {       fclose(inFile);
  282.                 writePhantomOutput(fileName);
  283.                 return 0;
  284.         }
  285.  
  286.         /* Use built-in pager if PAGER is not set or if this is for your eyes only,
  287.            this currently doesn't work, the _CONSOLE filename isn't used as the real
  288.            filename anymore */
  289.         if ((strcmp(fileName,CONSOLE_FILENAME) != 0)
  290.                 && (strlen(pager) != 0) && strcmp("pgp", pager))
  291.         {
  292.                 fclose(inFile);
  293. #ifdef UNIX
  294.                 if (strchr(fileName, '\'') != NULL)
  295.                         return(-1);
  296.                 sprintf(cmd, "%s '%s'", pager, fileName);
  297. #else
  298.                 sprintf(cmd, "%s %s", pager, fileName);
  299. #ifdef MSDOS
  300.                 for (p = cmd; *p; ++p)
  301.                         if (*p == '/')
  302.                                 *p = '\\';
  303. #endif
  304. #endif
  305.                 fflush(pgpout);
  306.                 return(system(cmd));
  307.         }
  308.  
  309. #ifdef UNIX
  310.         if (!isatty(fileno(stdout)))
  311.         {       fclose(inFile);
  312.                 writePhantomOutput(fileName);
  313.                 return 0;
  314.         }
  315. #endif /* UNIX */
  316.  
  317.         getScreenSize();
  318.  
  319.         /* Get file length */
  320.         fseek(inFile, 0L, SEEK_END);
  321.         fileLen = ftell(inFile);
  322.         if (!(fileLen))
  323.                 fileLen = 1;    /* avoid division thru' zero error! */
  324.         rewind(inFile);
  325.         lineno = 1;
  326.  
  327. #ifdef NEEDBREAK
  328.         ttycbreak();
  329. #endif
  330.         putchar('\n');
  331.         while (TRUE)
  332.         {   ch = getc(inFile);
  333.                 if (ch == LF)
  334.                 {   lines++;
  335.                         putchar('\n');
  336.                         chars = 0;
  337.                         ++lineno;
  338.                 }
  339.                 else
  340.                         if (ch == CR)
  341.                         {   lines++;
  342.                                 putchar('\n');
  343.                                 chars = 0;
  344.                                 ++lineno;
  345.  
  346.                                 /* Skip following LF if there is one */
  347.                                 if ((ch = getc(inFile)) != LF && ch != EOF)
  348.                                         ungetc(ch,inFile);
  349.                         }
  350.                         else
  351.                                 if (((unsigned char) ch >= ' ' && ch != EOF) || ch == TAB)
  352.                                 {   /* Legal char or tab, print it */
  353.                                         putchar(ch);
  354.                                         chars += (ch == TAB) ? 8 : 1;
  355.                                 }
  356.  
  357.                 /* If we've reach the max.no of columns we can handle, skip the
  358.                    rest of the line */
  359.                 if (chars == screen_columns - 1)
  360.                 {       chars = 0;
  361.                         while ((ch = getc(inFile)) != CR && ch != LF && ch != EOF )
  362.                                 ;
  363.                         if (ch != EOF)
  364.                                 ungetc(ch,inFile);
  365.                 }
  366.  
  367.                 /* If we've reached the max.no of rows we can handle, wait for the
  368.                    user to hit a key */
  369.                 while (ch == EOF || lines == screen_lines - 1)
  370.                 {       /* Print prompt at end of screen */
  371.                         reverse_attr();
  372.                         if (ch == EOF)
  373.                                 printf(PSTR("\nDone...hit any key\r"));
  374.                         else
  375.                                 printf(PSTR("More -- %d%% -- Hit space for next screen, Enter for new line, 'Q' to quit --\r"),
  376.                                         ( 100 * ftell( inFile ) ) / fileLen );
  377.                         norm_attr();
  378.                         fflush(stdout);
  379.                         c = getch();
  380.                         c = to_upper(c);
  381.  
  382.                         /* Blank out prompt */
  383.                         for (i=0; i<79; i++)
  384.                                 putchar(' ');
  385.                         putchar('\r');
  386.                         fflush(stdout);
  387.                         if (c == 'B' && lineno > screen_lines)          /* go Back a page */
  388.                         {       int seek_line = lineno - 2*screen_lines + 3;
  389.                                 lineno = 1;
  390.                                 rewind(inFile);
  391.                                 if (seek_line > 1)
  392.                                 {       printf("...skipping\n");
  393.                                         while ((ch = getc(inFile)) != EOF)
  394.                                                 if (ch == '\n')
  395.                                                         if (++lineno == seek_line)
  396.                                                                 break;
  397.                                 }
  398.                                 ch = '\0';
  399.                                 lines = 0;
  400.                         }
  401.                         else
  402.                         {       if (c == 'Q' || ch == EOF)
  403.                                         goto done;
  404.                                 if (c == ' ' || c == '\n' || c == '\r' || c == 'J')
  405.                                         lines -= (c == ' ') ? screen_lines - 2 : 1;     /* Do n more lines */
  406.                         }
  407.                 }
  408.         }
  409. done:
  410. #ifdef NEEDBREAK
  411.         ttynorm();
  412. #endif
  413.         fclose(inFile);
  414.         return(0);
  415. } /* more_file */
  416.  
  417.  
  418. /*
  419.  * open_more() and close_more() redirect pgpout to the pager.
  420.  *
  421.  */
  422.  
  423. static char *mfile = NULL;
  424. static boolean piping = FALSE;
  425. static FILE *savepgpout;
  426.  
  427.  
  428. int
  429. open_more(void)
  430. {
  431. #ifdef UNIX
  432.         char *p;
  433. #endif
  434.  
  435.         if (mfile || piping)
  436.                 close_more();
  437.  
  438.         savepgpout = pgpout;
  439. #ifdef UNIX
  440.         fflush(pgpout);
  441.         if (pager[0] == '\0')
  442.         {
  443.                 if ((p = my_getenv("PAGER")) != NULL)
  444.                         strncpy(pager, p, sizeof(pager) - 1);
  445.         }
  446.         /* Use built-in pager if PAGER is not set or set to "pgp" */
  447.         if ((strlen(pager) != 0) && strcmp("pgp", pager))
  448.         {
  449.                 if ((pgpout = popen(pager, "w")) != NULL)
  450.                 {       piping = TRUE;
  451.                         return 0;
  452.                 }
  453.                 perror("popen");
  454.                 pgpout = savepgpout;
  455.         }
  456. #endif
  457.         if ((mfile = tempfile(TMP_TMPDIR|TMP_WIPE)) == NULL)
  458.                 return -1;
  459.         if ((pgpout = fopen(mfile, FOPWTXT)) == NULL)
  460.         {
  461.                 pgpout = savepgpout;
  462.                 rmtemp(mfile);
  463.                 return -1;
  464.         }
  465.         /* user will not see anything until close_more() is called */
  466.         fprintf(savepgpout,PSTR("Just a moment..."));
  467.         fflush(savepgpout);
  468.         return 0;
  469. }
  470.  
  471. int
  472. close_more(void)
  473. {
  474.         if (!mfile && !piping)
  475.                 return 0;
  476.  
  477. #ifdef UNIX
  478.         if (piping)
  479.                 pclose(pgpout);
  480.         else
  481. #endif
  482.                 fclose(pgpout);
  483.         pgpout = savepgpout;
  484.         if (mfile)
  485.         {
  486.                 fprintf(pgpout,"\n");
  487.                 more_file(mfile);
  488.                 rmtemp(mfile);
  489.                 mfile = NULL;
  490.         }
  491.         piping = FALSE;
  492.         return 0;
  493. }
  494.